package ui;

import gov.nasa.worldwind.Movable;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.pick.PickSupport;
import gov.nasa.worldwind.pick.PickedObject;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.render.Material;
import gov.nasa.worldwind.render.PatternFactory;
import gov.nasa.worldwind.render.PreRenderable;
import gov.nasa.worldwind.render.Renderable;
import gov.nasa.worldwind.render.SurfaceIcon;
import gov.nasa.worldwind.render.markers.BasicMarker;
import gov.nasa.worldwind.render.markers.BasicMarkerAttributes;
import gov.nasa.worldwind.render.markers.Marker;
import gov.nasa.worldwind.render.markers.MarkerAttributes;
import gov.nasa.worldwind.render.markers.MarkerRenderer;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class SurfaceObject extends RenderableLayer{
	String id;
	CustomMarker marker;

	public SurfaceObject(String id, double lat, double lon, Material materialColor){
		this.id = id;
		Position position = Position.fromDegrees(lat, lon, 0);
		MarkerAttributes ma = new BasicMarkerAttributes();
		ma.setMaxMarkerSize(9e3);
		ma.setMinMarkerSize(9);
		ma.setMaterial(materialColor);
		marker = new CustomMarker(position, ma);
		marker.setHeading(Angle.ZERO);
		addRenderable(marker);
	}

	class CustomMarker extends BasicMarker implements PreRenderable, Renderable, Movable{
		private ArrayList<Marker> markerList;
		private MarkerRenderer markerRenderer;
		//         private SurfaceIcon headingIcon;
		private SurfaceIcon highlightIcon;
		private PickSupport pickSupport = new PickSupport();
		private SurfaceTrail trail = new SurfaceTrail();
		private Material savedMaterial;

		public CustomMarker(Position position, MarkerAttributes attrs){
			super(position, attrs);

			// Heading icon
			//             this.headingIcon = new SurfaceIcon("images/notched-compass.png", position);
			//             this.headingIcon.setOpacity(.5);
			//             this.headingIcon.setScale(.5);
			//             this.headingIcon.setMaxSize(50e3);
			//             this.headingIcon.setMaintainSize(true);

			// Highlight icon
			BufferedImage image = PatternFactory.createPattern(PatternFactory.PATTERN_CIRCLE, .3f, Color.WHITE);
			image = PatternFactory.blur(PatternFactory.blur(image, 5));
			this.highlightIcon = new SurfaceIcon(image, position);
			this.highlightIcon.setOpacity(.5);
			this.highlightIcon.setScale(3);
			this.highlightIcon.setVisible(false);
			this.highlightIcon.setMaintainSize(true);
		}

		public void setHighlighted(boolean state){
			if (this.highlightIcon.isVisible() == state)
				return;

			this.highlightIcon.setVisible(state);
			if (this.highlightIcon.isVisible()){
				this.savedMaterial = this.getAttributes().getMaterial();
				this.getAttributes().setMaterial(Material.RED);
			}
			else
				this.getAttributes().setMaterial(this.savedMaterial);
		}

		public void preRender(DrawContext dc){
			this.trail.preRender(dc);
			//             this.headingIcon.setHeading(this.getHeading());
			//             this.headingIcon.preRender(dc);
			this.highlightIcon.preRender(dc);
		}

		public void render(DrawContext dc){
			if (this.markerList == null){
				this.markerList = new ArrayList<Marker>();
				this.markerList.add(this);
			}
			if (this.markerRenderer == null){
				this.markerRenderer = new MarkerRenderer();
				this.markerRenderer.setOverrideMarkerElevation(true);
				this.markerRenderer.setElevation(0);
			}

			if (dc.isPickingMode()){
				this.markerRenderer.render(dc, this.markerList);

				// Separate pick color for the icon
				this.pickSupport.clearPickList();
				this.pickSupport.beginPicking(dc);
				java.awt.Color color = dc.getUniquePickColor();
				dc.getGL().glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue());
				//                 this.headingIcon.render(dc);
				PickedObject po = new PickedObject(color.getRGB(), this);
				po.setValue("Heading", true); // Attach heading key to picked object
				this.pickSupport.addPickableObject(po);
				this.pickSupport.endPicking(dc);
				this.pickSupport.resolvePick(dc, dc.getPickPoint(), null);
			}
			else{
				this.trail.render(dc);
				this.markerRenderer.render(dc, this.markerList);
				//                 this.headingIcon.render(dc);
				this.highlightIcon.render(dc);
			}
		}

		public Position getReferencePosition(){
			return this.getPosition();
		}

		public void move(Position delta){
			Position refPos = this.getReferencePosition();
			if (refPos == null)
				return;

			this.moveTo(refPos.add(delta));
		}

		public void moveTo(Position position){
			// Add current position to the trail
			Position refPos = this.getReferencePosition();
			if (refPos == null)
				return;

			this.trail.add(this.getReferencePosition());
			// Have the marker point in the move direction
			Angle heading = LatLon.greatCircleAzimuth(this.getReferencePosition(), position);
			this.setHeading(heading);
			// Update positions
			//             this.headingIcon.setLocation(position);
			this.highlightIcon.setLocation(position);
			this.setPosition(position);
		}
	}

	private class SurfaceTrail implements PreRenderable, Renderable{
		private int MAX_SIZE = 20;
		private ArrayList<SurfaceIcon> locations = new ArrayList<SurfaceIcon>();
		private BufferedImage imageSource = PatternFactory.createPattern(PatternFactory.PATTERN_CIRCLE, .3f,
				Color.WHITE);

		public void add(LatLon location)
		{
			// Add shape
			SurfaceIcon icon = new SurfaceIcon(this.imageSource, location);
			icon.setScale(.5);
			this.locations.add(icon);
			if (this.locations.size() > MAX_SIZE)
				this.locations.remove(0);

			// Fade out
			//             for (int i = 0; i < this.locations.size(); i++)
			//             {
			//                 this.locations.get(i).setOpacity(1d - (double) (this.locations.size() - i - 1) / MAX_SIZE);
			//             }
		}

		public void preRender(DrawContext dc){
			for (SurfaceIcon icon : this.locations){
				icon.preRender(dc);
			}
		}

		public void render(DrawContext dc){
			for (SurfaceIcon icon : this.locations){
				icon.render(dc);
			}
		}
	}
}
